package br.lotr.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public abstract class GenericDaoJpaImpl<T, PK extends Serializable> implements GenericDao<T,PK>{

	
    protected Class<?> entityClass;

    private static EntityManagerFactory fabrica;
    
    static {
    	fabrica = Persistence.createEntityManagerFactory("lotrConexao");
    }
    
    
	public GenericDaoJpaImpl(){
			ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
			this.entityClass = (Class<?>) genericSuperclass.getActualTypeArguments()[0];
			
	}

	protected EntityManager getEntityManager(){
		return fabrica.createEntityManager();
	}
		
    @Override
    public boolean salva(T t) {
    	EntityManager manager = getEntityManager();
    	try {
    		manager.getTransaction().begin();
    		manager.persist(t);
    		manager.getTransaction().commit();
    		return true;
    	} catch (Exception e) {
    		e.printStackTrace();
    		manager.getTransaction().rollback();
    		return false;
		} finally{
			manager.close();
		}
    	
    	
    }

    @SuppressWarnings("unchecked")
	@Override
    public T carrega(PK id) {
       	EntityManager manager = getEntityManager();
    	try {
    		manager.getTransaction().begin();
    		Object obj = manager.find(entityClass, id);
    		manager.getTransaction().commit();
    		return (T) obj;
    	} catch (Exception e) {
    		e.printStackTrace();
    		manager.getTransaction().rollback();
    		return null;
    	} finally{
			manager.close();
		}
    }

    @Override
    public boolean atualiza(T t) {
       	EntityManager manager = getEntityManager();
    	try {
    		manager.getTransaction().begin();
    		manager.merge(t);
    		manager.getTransaction().commit();
    		return true;
    	} catch (Exception e) {
    		e.printStackTrace();
    		manager.getTransaction().rollback();
    		return false;
		} finally{
			manager.close();
		}
    }

    @Override
    public boolean remove(PK id) {
    	
       	EntityManager manager = getEntityManager();
    	try {
    		manager.getTransaction().begin();
    		manager.remove(manager.find(entityClass, id));
    		manager.getTransaction().commit();
    		return true;
    	} catch (Exception e) {
    		e.printStackTrace();
    		manager.getTransaction().rollback();
    		return false;
		} finally{
			manager.close();
		}
        
    }
    
    @SuppressWarnings("unchecked")
	public List<?> getLista(){
    	EntityManager manager = getEntityManager();
    	CriteriaBuilder cb = manager.getCriteriaBuilder();
    	CriteriaQuery<T> c = (CriteriaQuery<T>) cb.createQuery(entityClass);
    	Root<T> root = (Root<T>) c.from(entityClass);
    	c.select(root);
    	
    	TypedQuery<T> query = manager.createQuery(c);
    	List<?> lista = query.getResultList();
    	return lista;
    
    }
 }